package com.szxx.suit;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import com.szxx.constans.PokerGameConstant;
import com.szxx.domain.Card;
import com.szxx.domain.Cards;

/**
 * 斗地主牌型算法工具类 <br>
 *
 * @author Ambrose
 */
public class DdzTypeUtil {
	
	/**
	 * 斗地主牌，根据 value还原 number值
	 * 
	 * @param value
	 * @return
	 */
	public final static int getNumberByValue(int value) {
		if (value == PokerGameConstant.RED_JOKER_SHAPE_VALUE) {
			return PokerGameConstant.RED_JOKER_SHAPE_NUM;
		} else if (value == PokerGameConstant.BLACK_JOKER_SHAPE_VALUE) {
			return PokerGameConstant.BLACK_JOKER_SHAPE_NUM;
		} else if (value == PokerGameConstant.NUMBER_2_VALUE) {
			return 2;
		} else if (value == PokerGameConstant.NUMBER_1_VALUE) {
			return 1;
		} else { // 1 - 13
			return value;
		}
	}
	
	/**
	 * 是否可以找到相应顺几张的顺子 <br>
	 * 期间可以用癞子去做填补，癞子不够也不行
	 * 
	 * @param beginValue 开始值
	 * @param tupleSize 元组牌数量
	 * @param straightNeed 每顺几张，单顺，双顺，三顺
	 * @param cards
	 * @param term
	 * @param result
	 * @return
	 */
	public final static boolean ensureStaight(int beginValue, int tupleSize, int straightNeed
			, Cards cards, AbstractSuitTerm term, DdzAnalysisResult result) {
		int laiziCardNum = result.getLaziCardNum();
		int allNeedLaiziCardNum = 0;
		int tupleNum = result.getCardNum() / tupleSize; // 分析有几组牌
		for (int valueTemp = beginValue; valueTemp > beginValue - tupleNum; valueTemp--) { // 从大到小
			if (valueTemp < PokerGameConstant.NUMBER_3_VALUE) { // 不能继续顺下去
				return false;
			}
			int valueTempNum = result.getNoneLaziValueCounter().getValueCount(valueTemp);
			int needLaziNum = straightNeed - valueTempNum; 
			needLaziNum = needLaziNum > 0 ? needLaziNum : 0; // 防止出现负数
			allNeedLaiziCardNum += needLaziNum;
			if (laiziCardNum < allNeedLaiziCardNum) { // 癞子不够
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 是否可以找到相应顺几张的顺子 <br>
	 * 期间可以用癞子去做填补，癞子不够也不行
	 * 
	 * @param beginValue 开始值
	 * @param tupleSize 元组牌数量
	 * @param straightNeed 每顺几张，单顺，双顺，三顺
	 * @param tupleNum 顺几组 34567 顺5组  334455 顺三组
	 * @param cards
	 * @param term
	 * @param result
	 * @return
	 */
	public final static boolean ensureTupleStaightDesc(int beginValue, int tupleNum, int straightNeed
			, Cards cards, AbstractSuitTerm term, DdzAnalysisResult result) {
		int laiziCardNum = result.getLaziCardNum();
		int allNeedLaiziCardNum = 0;
		for (int valueTemp = beginValue; valueTemp > beginValue - tupleNum; valueTemp--) { // 从大到小
			if (valueTemp < PokerGameConstant.NUMBER_3_VALUE) { // 不能继续顺下去
				return false;
			}
			int valueTempNum = result.getNoneLaziValueCounter().getValueCount(valueTemp);
			int needLaziNum = straightNeed - valueTempNum; 
			needLaziNum = needLaziNum > 0 ? needLaziNum : 0; // 防止出现负数
			allNeedLaiziCardNum += needLaziNum;
			if (laiziCardNum < allNeedLaiziCardNum) { // 癞子不够
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 提同值牌算法，从手牌中分析出n张同值牌出来 <br>
	 * 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
	 * 
	 * @param cards
	 * @param tupleCount 数量限制
	 * @return
	 */
	public static List<Cards> selectTupleCountCards(Cards cards, int tupleCount) {
		List<Cards> cardsResult = new LinkedList<Cards>();
		DdzAnalysisResult result = (DdzAnalysisResult) cards.getResult();
		result.collectNumber(cards, null);
		List<Integer> allValues = result.getAllValueCounter().getAllValues();
		// 直接寻找
		for (Integer valueTemp : allValues) {
			if (result.getAllValueCounter().getValueCount(valueTemp) == tupleCount) {
				List<Card> partCardList = DdzTypeUtil.cloneObtainedCards(cards, valueTemp, tupleCount);
				cardsResult.add(DdzTypeUtil.createCardsCopy(partCardList));
			}
		}
		// 拆牌（三张，炸弹）获取
		for (Integer valueTemp : allValues) {
			if (result.getAllValueCounter().getValueCount(valueTemp) > tupleCount) {
				List<Card> partCardList = DdzTypeUtil.cloneObtainedCards(cards, valueTemp, tupleCount);
				cardsResult.add(DdzTypeUtil.createCardsCopy(partCardList));
			}
		}
		return cardsResult;
	}
	
	/**
	 * 提单张牌算法，从手牌中分析出单张牌出来 <br>
	 * 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
	 * 
	 * @param cards
	 * @param takeJoker
	 * @return
	 */
	public static List<Cards> selectSingleCards(Cards cards, boolean takeJoker) {
		List<Cards> cardsResult = selectTupleCountCards(cards, 1);
		if (!takeJoker) { // 不允许带王
			for (Iterator<Cards> iterator = cardsResult.iterator(); iterator.hasNext();) {
				Cards cardsTemp = (Cards) iterator.next();
				if (cardsTemp.get(0).getValue() == PokerGameConstant.RED_JOKER_SHAPE_VALUE
						|| cardsTemp.get(0).getValue() == PokerGameConstant.BLACK_JOKER_SHAPE_VALUE) {
					iterator.remove();
				}
			}
		}
		return cardsResult;
	}
	
	/**
	 * 从指定牌列中获取部分牌，原牌不变
	 * 
	 * @param cards
	 * @param value 指定牌value值
	 * @param count 数量
	 * @return
	 */
	public final static List<Card> cloneSublistedCards(Cards cards, int fromIndex, int toIndex) {
		List<Card> cardsResult = new LinkedList<Card>();
		List<Card> cardList = cards.subList(fromIndex, toIndex);
		for (Card cardTemp : cardList) {
			cardsResult.add(cardTemp.clone());
		}
		return cardsResult;
	}
	
	/**
	 * 从指定牌列中获取部分牌，原牌不变
	 * 
	 * @param cards
	 * @param value 指定牌value值
	 * @param count 数量
	 * @return
	 */
	public final static List<Card> cloneObtainedCards(Cards cards, int value, int need) {
		List<Card> cardsResult = new LinkedList<Card>();
		if (need > 0) {
			for (Card cardTemp : cards) {
				if (cardTemp.getValue() == value) {
					cardsResult.add(cardTemp.clone());
					need--;
					if (need == 0) {
						break;
					}
				}
			}
		}
		return cardsResult;
	}
	
	/**
	 * 从指定牌列中获取部分牌，原牌中移除
	 * 
	 * @param cards
	 * @param value 指定牌value值
	 * @param count 数量
	 * @return
	 */
	public final static List<Card> cloneRemovedCards(Cards cards, int value, int need) {
		List<Card> removedCards = new LinkedList<Card>();
		if (need > 0) {
			for (Iterator<Card> iterator = cards.iterator(); iterator.hasNext();) {
				Card cardTemp = iterator.next();
				if (cardTemp.getValue() == value) {
					removedCards.add(cardTemp.clone());
					iterator.remove();
					need--;
					if (need == 0) {
						break;
					}
				}
			}
		}
		return removedCards;
	}
	
	/**
	 * 创建Cards对象，引用的牌为深克隆
	 * 
	 * @param cardList
	 * @return
	 */
	public final static Cards createCardsCopy(List<Card> cardList) {
		return cloneCardsAndAddCardList(null, cardList);
	}
	
	/**
	 * 复制（深克隆）一副牌，添加部分牌
	 * 
	 * @param cardList
	 * @return
	 */
	public final static Cards cloneCardsAndAddCardList(Cards cards, List<Card> cardList) {
		Cards copy = null;
		if (cards == null) {
			copy = new Cards();
		} else {
			copy = cards.clone();
		}
		if (cardList != null) {
			for (Card card : cardList) {
				copy.addCard(card.clone());
			}
		}
		return copy;
	}
	
	/**
	 * 复制（深克隆）一副牌，添加部分牌
	 * 
	 * @param cardList
	 * @param addCards
	 * @return
	 */
	public final static Cards cloneCardsAndAddCards(Cards cards, Cards addCards) {
		Cards copy = null;
		if (cards == null) {
			copy = new Cards();
		} else {
			copy = cards.clone();
		}
		if (addCards != null) {
			copy.addCards(addCards.clone());
		}
		return copy;
	}
	
	/**
	 * 复制（深克隆）一副牌，去掉部分牌
	 * 
	 * @param cardList
	 * @param removeCards
	 * @return
	 */
	public final static Cards cloneCardsAndRemoveCards(Cards cards, Cards removeCards) {
		Cards copy = null;
		if (cards == null) {
			copy = new Cards();
		} else {
			copy = cards.clone();
		}
		if (removeCards != null) {
			for (Card card : removeCards) {
				copy.remove(card);
			}
		}
		return copy;
	}
	
}
